home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / fsrmt / fsrmtFile.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  53KB  |  1,716 lines

  1. /* 
  2.  * fsRmtFile.c --
  3.  *
  4.  *    Routines for operations on remote files.  The I/O operations
  5.  *    check in the cache, and then use the raw remote I/O operations
  6.  *    to transfer data to and from the remote file server.
  7.  *
  8.  * Copyright 1987 Regents of the University of California
  9.  * All rights reserved.
  10.  * Permission to use, copy, modify, and distribute this
  11.  * software and its documentation for any purpose and without
  12.  * fee is hereby granted, provided that the above copyright
  13.  * notice appear in all copies.  The University of California
  14.  * makes no representations about the suitability of this
  15.  * software for any purpose.  It is provided "as is" without
  16.  * express or implied warranty.
  17.  */
  18.  
  19. #ifndef lint
  20. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/fsrmt/fsrmtFile.c,v 1.14 92/12/13 18:17:01 mgbaker Exp $ SPRITE (Berkeley)";
  21. #endif not lint
  22.  
  23.  
  24. #include <sprite.h>
  25. #include <fs.h>
  26. #include <fsutil.h>
  27. #include <fsconsist.h>
  28. #include <fsioFile.h>
  29. #include <fslcl.h>
  30. #include <fscache.h>
  31. #include <fsdm.h>
  32. #include <fsStat.h>
  33. #include <fsprefix.h>
  34. #include <fsNameOps.h>
  35. #include <fsrmt.h>
  36. #include <recov.h>
  37.  
  38. #include <rpc.h>
  39. #include <vm.h>
  40.  
  41. #include <stdio.h>
  42.  
  43. static ReturnStatus FsrmtFileBlockRead _ARGS_((Fs_HandleHeader *hdrPtr, 
  44.         Fscache_Block *blockPtr, Sync_RemoteWaiter *waitPtr));
  45. static ReturnStatus FsrmtFileBlockWrite _ARGS_((Fs_HandleHeader *hdrPtr, 
  46.         Fscache_Block *blockPtr, int flags));
  47. static ReturnStatus FsrmtFileBlockAllocate _ARGS_((Fs_HandleHeader *hdrPtr, 
  48.         int offset, int numBytes, int flags, int *blockAddrPtr, 
  49.         Boolean *newBlockPtr));
  50. static ReturnStatus FsrmtFileTrunc _ARGS_((Fs_HandleHeader *hdrPtr, int size,
  51.                       Boolean delete));
  52.                 /* Second param for ASPLOS only.  Remove
  53.                  * when that's over.  -Mary 2/15/92. */
  54. static Boolean FsrmtStartWriteBack _ARGS_((Fscache_Backend *backendPtr, Boolean fileFsynced));
  55.  
  56. static void FsrmtReallocBlock _ARGS_((ClientData data, 
  57.         Proc_CallInfo *callInfoPtr));
  58.  
  59. static Fscache_BackendRoutines  fsrmtBackendRoutines = {
  60.         FsrmtFileBlockAllocate,
  61.         FsrmtFileTrunc,
  62.         FsrmtFileBlockRead,
  63.         FsrmtFileBlockWrite,
  64.         FsrmtReallocBlock,
  65.         FsrmtStartWriteBack,
  66.  
  67. };
  68. static     Fscache_Backend *cacheBackendPtr = (Fscache_Backend *) NIL;
  69.  
  70. static Boolean FileMatch _ARGS_((Fscache_FileInfo *cacheInfoPtr, 
  71.         ClientData cleintData));
  72. static Boolean BlockMatch _ARGS_((Fscache_Block *blockPtr,
  73.         ClientData cleintData));
  74.  
  75. static Sync_Lock rmtCleanerLock = Sync_LockInitStatic("Fs:rmtCleanerLock");
  76. #define    LOCKPTR    &rmtCleanerLock
  77.  
  78. int    fsrmtBlockCleaners = 0;
  79.  
  80.  
  81. /*
  82.  *----------------------------------------------------------------------
  83.  *
  84.  * FsRmtFileHandleInit --
  85.  *
  86.  *    Initialize a handle for a remote file from the file state
  87.  *    returned by the server.
  88.  *
  89.  * Results:
  90.  *    SUCCESS.
  91.  *
  92.  * Side effects:
  93.  *    Create and install a handle for the file.
  94.  *
  95.  *----------------------------------------------------------------------
  96.  */
  97. ReturnStatus
  98. FsRmtFileHandleInit(fileIDPtr, fileStatePtr, openForWriting, name,
  99.     newHandlePtrPtr)
  100.     Fs_FileID        *fileIDPtr;
  101.     Fsio_FileState        *fileStatePtr;
  102.     Boolean        openForWriting;
  103.     char        *name;
  104.     Fsrmt_FileIOHandle    **newHandlePtrPtr;
  105. {
  106.     register Fsrmt_FileIOHandle *handlePtr;
  107.     Boolean found;
  108.     int        size;
  109.  
  110.     /*
  111.      * Since both Fsrmt_FileIOHandle and Fsio_FileIOHandle are so 
  112.      * popular on the root file server we try to use the same memory
  113.      * size for both.  We choose to allocate the large of the two.
  114.      */
  115.     size = sizeof(Fsrmt_FileIOHandle);
  116.     if (size < sizeof(Fsio_FileIOHandle)) {
  117.     size = sizeof(Fsio_FileIOHandle);
  118.     }
  119.  
  120.     found = Fsutil_HandleInstall(fileIDPtr, size, name,
  121.             FALSE, (Fs_HandleHeader **)newHandlePtrPtr);
  122.     handlePtr = *newHandlePtrPtr;
  123.     if (found) {
  124.     /*
  125.      * Update attributes cached in the handle, and verify the
  126.      * validity of any cached data blocks.
  127.      */
  128.     if (Fscache_UpdateFile(&handlePtr->cacheInfo, openForWriting,
  129.             fileStatePtr->version, fileStatePtr->cacheable,
  130.             &fileStatePtr->attr)) {
  131.         Vm_FileChanged(&handlePtr->segPtr);
  132.     }
  133.     /* 
  134.      * Update the handle's open time stamp.  This is used to catch races
  135.      * between near-simultanous opens on a client and related cache
  136.      * consistency messasge.
  137.      */
  138.     handlePtr->openTimeStamp = fileStatePtr->openTimeStamp;
  139.     } else {
  140.     if (cacheBackendPtr == (Fscache_Backend *) NIL) {
  141.         cacheBackendPtr = 
  142.         Fscache_RegisterBackend(&fsrmtBackendRoutines,(ClientData)0,0);
  143.     }
  144.     /*
  145.      * Initialize the new handle.  There is no cache validation to
  146.      * be done because blocks are only cached when a handle is present.
  147.      */
  148.     Fscache_FileInfoInit(&handlePtr->cacheInfo, (Fs_HandleHeader *)handlePtr,
  149.         fileStatePtr->version, fileStatePtr->cacheable,
  150.         &fileStatePtr->attr, cacheBackendPtr);
  151.  
  152.     Fsutil_RecoveryInit(&handlePtr->rmt.recovery);
  153.     Fscache_ReadAheadInit(&handlePtr->readAhead);
  154.  
  155.     handlePtr->flags = 0;
  156.     handlePtr->openTimeStamp = fileStatePtr->openTimeStamp;
  157.     handlePtr->segPtr = (Vm_Segment *)NIL;
  158.     fs_Stats.object.rmtFiles++;
  159.     }
  160.     if (fileStatePtr->newUseFlags & FS_DIR) {
  161.     handlePtr->cacheInfo.flags |= FSCACHE_IS_DIR;
  162.     }
  163.     free((Address)fileStatePtr);
  164.     return(SUCCESS);
  165. }
  166.  
  167. /*
  168.  *----------------------------------------------------------------------
  169.  *
  170.  * FsrmtFileIoOpen --
  171.  *
  172.  *      Set up a stream for a remote disk file.  This is called from Fs_Open
  173.  *    to complete the opening of a stream. By this time any cache consistency
  174.  *    actions have already been taken.
  175.  *
  176.  * Results:
  177.  *    SUCCESS, until FsRmtFileHandleInit returns differently.
  178.  *
  179.  * Side effects:
  180.  *    Installs the handle for the file and updates the use counts
  181.  *    (ref, write, exec) due to this open.
  182.  *
  183.  *----------------------------------------------------------------------
  184.  */
  185. /*ARGSUSED*/
  186. ReturnStatus
  187. FsrmtFileIoOpen(ioFileIDPtr, flagsPtr, clientID, streamData, name,
  188.     ioHandlePtrPtr)
  189.     Fs_FileID        *ioFileIDPtr;    /* I/O fileID from the name server */
  190.     int            *flagsPtr;    /* New ones from the server returned */
  191.     int            clientID;    /* IGNORED */
  192.     ClientData        streamData;    /* Reference to Fsio_FileState struct */
  193.     char        *name;        /* File name for error msgs */
  194.     Fs_HandleHeader    **ioHandlePtrPtr;/* Return - a handle set up for
  195.                      * I/O to a file, NIL if failure. */
  196. {
  197.     ReturnStatus        status;
  198.     Fsio_FileState            *fileStatePtr;
  199.     register int         flags;
  200.     register Fsrmt_FileIOHandle *rmtHandlePtr;
  201.  
  202.     fileStatePtr = (Fsio_FileState *)streamData;
  203.     flags = fileStatePtr->newUseFlags;
  204.  
  205.     status = FsRmtFileHandleInit(ioFileIDPtr, fileStatePtr,
  206.         (flags & FS_WRITE), name, (Fsrmt_FileIOHandle **)ioHandlePtrPtr);
  207.     if (status == SUCCESS) {
  208.     rmtHandlePtr = (Fsrmt_FileIOHandle *)*ioHandlePtrPtr;
  209.     /*
  210.      * Update our use information to reflect the open.
  211.      */
  212.     rmtHandlePtr->rmt.recovery.use.ref++;
  213.     if (flags & FS_WRITE) {
  214.         rmtHandlePtr->rmt.recovery.use.write++;
  215.     }
  216.     if (flags & FS_EXECUTE) {
  217.         rmtHandlePtr->rmt.recovery.use.exec++;
  218.     }
  219.     /*
  220.      * Note if we are a swap file in case of recovery later.
  221.      */
  222.     rmtHandlePtr->flags |= (flags & FS_SWAP);
  223.     *flagsPtr = flags;
  224.     Fsutil_HandleUnlock(rmtHandlePtr);
  225.     }
  226.     return(status);
  227. }
  228.  
  229. /*
  230.  *----------------------------------------------------------------------
  231.  *
  232.  * FsrmtFileReopen --
  233.  *
  234.  *    Reopen a remote file.  This sets up and conducts an 
  235.  *    RPC_FS_REOPEN remote procedure call to re-open the remote file.
  236.  *
  237.  * Results:
  238.  *    A  non-SUCCESS return code if the re-open was attempted and failed.
  239.  *    FS_NO_HANDLE if we delete the handle.
  240.  *
  241.  * Side effects:
  242.  *    If the reopen works we'll have updated cached attributes, version
  243.  *    number, etc.
  244.  *
  245.  *----------------------------------------------------------------------
  246.  */
  247. /*ARGSUSED*/
  248. ReturnStatus
  249. FsrmtFileReopen(hdrPtr, clientID, inData, outSizePtr, outDataPtr)
  250.     Fs_HandleHeader    *hdrPtr;
  251.     int            clientID;        /* Should be rpc_SpriteID */
  252.     ClientData        inData;            /* IGNORED */
  253.     int            *outSizePtr;        /* IGNORED */
  254.     ClientData        *outDataPtr;        /* IGNORED */
  255. {
  256.     register Fsrmt_FileIOHandle    *rmtHandlePtr;
  257.     ReturnStatus        status;
  258.     Fsio_FileReopenParams        reopenParams;
  259.     Fsio_FileState            fileState;
  260.     register int        numDirtyBlocks;
  261.     int                outSize;
  262.  
  263.     rmtHandlePtr = (Fsrmt_FileIOHandle *)hdrPtr;
  264.     numDirtyBlocks = Fscache_PreventWriteBacks(&rmtHandlePtr->cacheInfo);
  265.     Fscache_AllowWriteBacks(&rmtHandlePtr->cacheInfo);
  266.     /*
  267.      * Optimize out re-opens for files that aren't being waited
  268.      * on, that have no users, and that have no blocks in the cache.
  269.      * I don't call OkToScavenge from fsutilHandleScavenge.c, since I think
  270.      * it's okay to do this even if there's already an active scavenger,
  271.      * because it will have locked the handle if it's working on it.
  272.      */
  273.     if (recov_SkipCleanFiles && (rmtHandlePtr->rmt.recovery.use.ref == 0 &&
  274.         Fscache_OkToScavengeExceptDirty(&rmtHandlePtr->cacheInfo) &&
  275.         !Fsutil_RecoveryNeeded(&rmtHandlePtr->rmt.recovery))) {
  276.     fs_Stats.recovery.reopensAvoided++;
  277.     return FS_RECOV_SKIP;
  278.     } else if (!recov_SkipCleanFiles &&
  279.         (rmtHandlePtr->rmt.recovery.use.ref == 0 &&
  280.         Fscache_OkToScavengeExceptDirty(&rmtHandlePtr->cacheInfo) &&
  281.         !Fsutil_RecoveryNeeded(&rmtHandlePtr->rmt.recovery))) {
  282.         Vm_FileChanged(&rmtHandlePtr->segPtr);
  283.         Fsutil_RecoverySyncLockCleanup(&rmtHandlePtr->rmt.recovery);
  284.         Fscache_InfoSyncLockCleanup(&rmtHandlePtr->cacheInfo);
  285.         Fscache_ReadAheadSyncLockCleanup(&rmtHandlePtr->readAhead);
  286.         Fsutil_HandleRemove(rmtHandlePtr);
  287.         fs_Stats.object.rmtFiles--;
  288.     fs_Stats.recovery.reopensAvoided++;
  289.     return FS_NO_HANDLE;
  290.     }
  291. /* for debugging */
  292. #define    FS_HANDLE_INVALID 0x20
  293.     if (hdrPtr->flags & FS_HANDLE_INVALID) {
  294.     printf("Attempting to recover invalid file handle <%d,0x%x,0x%x>\n",
  295.         hdrPtr->fileID.serverID, hdrPtr->fileID.major,
  296.         hdrPtr->fileID.minor);
  297.     return SUCCESS;
  298.     }
  299. /* end for debugging */
  300.     reopenParams.flags = rmtHandlePtr->flags;
  301.     if (numDirtyBlocks > 0) {
  302.     reopenParams.flags |= FSIO_HAVE_BLOCKS;
  303.     }
  304.     reopenParams.fileID = hdrPtr->fileID;
  305.     reopenParams.fileID.type = FSIO_LCL_FILE_STREAM;
  306.     reopenParams.prefixFileID.type = NIL;    /* not used */
  307.     reopenParams.use = rmtHandlePtr->rmt.recovery.use;
  308.     reopenParams.version = rmtHandlePtr->cacheInfo.version;
  309.  
  310.     /*
  311.      * Contact the server to do the reopen.  We have to unlock the handle
  312.      * here in case the server asks us to write-back or invalidate.
  313.      */
  314.     outSize = sizeof(Fsio_FileState);
  315.     Fsutil_HandleUnlock(hdrPtr);
  316.     status = FsrmtReopen(hdrPtr, sizeof(Fsio_FileReopenParams),
  317.         (Address)&reopenParams, &outSize, (Address)&fileState);
  318.     Fsutil_HandleLock(hdrPtr);
  319.     if (status != SUCCESS) {
  320.     if (numDirtyBlocks > 0) {
  321.         printf(
  322. "Re-open failed <%x> with dirty blocks in cache, \"%s\" <%d,%d> server %d\n",
  323.         status, Fsutil_HandleName(hdrPtr), hdrPtr->fileID.major,
  324.         hdrPtr->fileID.minor, hdrPtr->fileID.serverID);
  325.     }
  326.     if (status != RPC_TIMEOUT &&
  327.         status != RPC_SERVICE_DISABLED) {
  328.         /*
  329.          * Nuke the cache because our caller will nuke the handle.
  330.          */
  331.         Fscache_FileInvalidate(&rmtHandlePtr->cacheInfo, 0, FSCACHE_LAST_BLOCK);
  332.     }
  333.     } else {
  334.     /*
  335.      * Flush any lanquishing dirty blocks back to the server.
  336.      */
  337.     if (numDirtyBlocks > 0) {
  338.         int skipped;
  339.         (void) Fscache_FileWriteBack(&rmtHandlePtr->cacheInfo, 0,
  340.                 FSCACHE_LAST_BLOCK, 0, &skipped);
  341.     }
  342.     /*
  343.      * Update the handle - take care of cache flushes, updating cached
  344.      * attributes, etc.
  345.      */
  346.     if (Fscache_UpdateFile(&rmtHandlePtr->cacheInfo,
  347.             rmtHandlePtr->rmt.recovery.use.write,
  348.             fileState.version, fileState.cacheable,
  349.             &fileState.attr)) {
  350.         Vm_FileChanged(&rmtHandlePtr->segPtr);
  351.     }
  352.  
  353.     rmtHandlePtr->openTimeStamp = fileState.openTimeStamp;
  354.     }
  355.     return(status);
  356. }
  357.  
  358. /*
  359.  *----------------------------------------------------------------------
  360.  *
  361.  * FsrmtFileClose -- 
  362.  *
  363.  *    Close time processing for remote files.
  364.  *
  365.  * Results:
  366.  *    SUCCESS.
  367.  *
  368.  * Side effects:
  369.  *    This decrements the local use counts, then synchronizes
  370.  *    with write-backs before telling the server about the close.
  371.  *
  372.  *----------------------------------------------------------------------
  373.  */
  374.  
  375. /*ARGSUSED*/
  376. ReturnStatus
  377. FsrmtFileClose(streamPtr, clientID, procID, flags, dataSize, closeData)
  378.     Fs_Stream        *streamPtr;    /* Stream to remote file */
  379.     int            clientID;    /* HostID of client closing */
  380.     Proc_PID        procID;        /* Process ID of closer */
  381.     int            flags;        /* Flags from the stream being closed */
  382.     int            dataSize;    /* Size of closeData */
  383.     ClientData        closeData;    /* NIL on entry. */
  384. {
  385.     register ReturnStatus status;
  386.     register Fsrmt_FileIOHandle *handlePtr =
  387.         (Fsrmt_FileIOHandle *)streamPtr->ioHandlePtr;
  388.     /*
  389.      * Decrement local references.
  390.      */
  391.  
  392.     handlePtr->rmt.recovery.use.ref--;
  393.     if (flags & FS_WRITE) {
  394.     handlePtr->rmt.recovery.use.write--;
  395.     }
  396.     if (flags & FS_EXECUTE) {
  397.     handlePtr->rmt.recovery.use.exec--;
  398.     }
  399.     if (handlePtr->rmt.recovery.use.ref < 0 ||
  400.     handlePtr->rmt.recovery.use.write < 0 ||
  401.     handlePtr->rmt.recovery.use.exec < 0) {
  402.     panic("FsrmtFileClose: <%d,%d> ref %d write %d exec %d\n",
  403.         handlePtr->rmt.hdr.fileID.major, handlePtr->rmt.hdr.fileID.minor,
  404.         handlePtr->rmt.recovery.use.ref,
  405.         handlePtr->rmt.recovery.use.write,
  406.         handlePtr->rmt.recovery.use.exec);
  407.     }
  408.     if (!Fsutil_HandleValid((Fs_HandleHeader *)handlePtr)) {
  409.     status = FS_FILE_REMOVED;
  410.     } else {
  411.     if (handlePtr->rmt.recovery.use.ref == 0) {
  412.         int    numDirtyBlocks;
  413.         /*
  414.          * Synchronize closes and delayed writes.  We wait for writes
  415.          * in progress to complete. 
  416.          */
  417.         numDirtyBlocks =  Fscache_PreventWriteBacks(&handlePtr->cacheInfo);
  418.         if (numDirtyBlocks == 0) {
  419.         /*
  420.          * Inform the server on the close requests the we don't
  421.          * have any dirty blocks for the file.
  422.          */
  423.         flags |= FS_LAST_DIRTY_BLOCK;
  424.         }
  425.     }
  426.     status = Fsrmt_Close(streamPtr, clientID, procID, flags,
  427.         sizeof(Fscache_Attributes), (ClientData)&handlePtr->cacheInfo.attr);
  428.     }
  429.  
  430.     if (status == FS_FILE_REMOVED && handlePtr->rmt.recovery.use.ref == 0) {
  431.     /*
  432.      * Nuke our cache after we've finished with this (now bogus) handle.
  433.      * (Apparently we let the handle linger and get scavenged.  Could
  434.      * change things to remove the handle here.)
  435.      */
  436.     Fscache_Trunc(&handlePtr->cacheInfo, 0, FSCACHE_TRUNC_DELETE);
  437.     }
  438.     Fscache_AllowWriteBacks(&handlePtr->cacheInfo);
  439.     Fsutil_HandleRelease(handlePtr, TRUE);
  440.     return(SUCCESS);
  441. }
  442.  
  443. /*
  444.  *----------------------------------------------------------------------
  445.  *
  446.  * FsrmtFileScavenge --
  447.  *
  448.  *    Called peridocally to see if we still need the handle for
  449.  *    the remote file.
  450.  *
  451.  * Results:
  452.  *    TRUE if it removed the handle.
  453.  *
  454.  * Side effects:
  455.  *    Either removes or unlocks the handle.
  456.  *
  457.  *----------------------------------------------------------------------
  458.  */
  459. Boolean
  460. FsrmtFileScavenge(hdrPtr)
  461.     Fs_HandleHeader *hdrPtr;
  462. {
  463.     register Fsrmt_FileIOHandle *handlePtr = (Fsrmt_FileIOHandle *)hdrPtr;
  464.     if (handlePtr->rmt.recovery.use.ref == 0 &&
  465.     Fscache_OkToScavenge(&handlePtr->cacheInfo) &&
  466.     !Fsutil_RecoveryNeeded(&handlePtr->rmt.recovery)) {
  467.     /*
  468.      * Remove handles for files with no users and no blocks in cache.
  469.      */
  470.     Vm_FileChanged(&handlePtr->segPtr);
  471.     Fsutil_RecoverySyncLockCleanup(&handlePtr->rmt.recovery);
  472.     Fscache_InfoSyncLockCleanup(&handlePtr->cacheInfo);
  473.     Fscache_ReadAheadSyncLockCleanup(&handlePtr->readAhead);
  474.     Fsutil_HandleRemove(handlePtr);
  475.     fs_Stats.object.rmtFiles--;
  476.     return(TRUE);
  477.     } else {
  478.     Fsutil_HandleUnlock(handlePtr);
  479.     return(FALSE);
  480.     }
  481. }
  482.  
  483. /*
  484.  *----------------------------------------------------------------------
  485.  *
  486.  * FsrmtFileVerify --
  487.  *
  488.  *    Map from a remote client's fileID to a local fileID and
  489.  *    verify that the remote client is known.
  490.  *
  491.  * Results:
  492.  *    A pointer to the local handle for the file, or NIL if
  493.  *    the client is bad.
  494.  *
  495.  * Side effects:
  496.  *    Changes the client's fileID type to FSIO_LCL_FILE_STREAM and
  497.  *    fetches the local handle.  The handle is returned locked.
  498.  *
  499.  *----------------------------------------------------------------------
  500.  */
  501.  
  502. Fs_HandleHeader *
  503. FsrmtFileVerify(fileIDPtr, clientID, domainTypePtr)
  504.     Fs_FileID    *fileIDPtr;    /* Client's fileID */
  505.     int        clientID;    /* Host ID of the client */
  506.     int        *domainTypePtr;    /* Return - FS_LOCAL_DOMAIN */
  507. {
  508.     register Fsio_FileIOHandle *handlePtr;
  509.     register Fsconsist_ClientInfo    *clientPtr;
  510.     Boolean            found = FALSE;
  511.  
  512.     fileIDPtr->type = FSIO_LCL_FILE_STREAM;
  513.     handlePtr = Fsutil_HandleFetchType(Fsio_FileIOHandle, fileIDPtr);
  514.     if (handlePtr != (Fsio_FileIOHandle *)NIL) {
  515.     LIST_FORALL(&handlePtr->consist.clientList, (List_Links *) clientPtr) {
  516.         if (clientPtr->clientID == clientID) {
  517.         found = TRUE;
  518.         break;
  519.         }
  520.     }
  521.     if (!found) {
  522.         printf(
  523.         "FsrmtFileVerify: \"%s\" <%d,%d> client %d not found\n",
  524.         Fsutil_HandleName(handlePtr), fileIDPtr->major, fileIDPtr->minor,
  525.         clientID);
  526.         Fsutil_HandleRelease(handlePtr, TRUE);
  527.         handlePtr = (Fsio_FileIOHandle *)NIL;
  528.     }
  529.     } else {
  530.     printf( "FsrmtFileVerify, no handle <%d,%d> client %d\n",
  531.         fileIDPtr->major, fileIDPtr->minor, clientID);
  532.     }
  533.     if (domainTypePtr != (int *)NIL) {
  534.     *domainTypePtr = FS_LOCAL_DOMAIN;
  535.     }
  536.     return((Fs_HandleHeader *)handlePtr);
  537. }
  538.  
  539. /*
  540.  * ----------------------------------------------------------------------------
  541.  *
  542.  * FsrmtFileMigClose --
  543.  *
  544.  *    Release recovery use counts on a remote file.  This is called when
  545.  *    a stream to the file has migrated away.
  546.  *
  547.  * Results:
  548.  *    SUCCESS.
  549.  *
  550.  * Side effects:
  551.  *    Decrement use counts and release the handle.
  552.  *
  553.  * ----------------------------------------------------------------------------
  554.  *
  555.  */
  556. /*ARGSUSED*/
  557. ReturnStatus
  558. FsrmtFileMigClose(hdrPtr, flags)
  559.     Fs_HandleHeader *hdrPtr;    /* File being encapsulated */
  560.     int flags;            /* Use flags from the stream */
  561. {
  562.     register Fsrmt_FileIOHandle *handlePtr = (Fsrmt_FileIOHandle *)hdrPtr;
  563.  
  564.     Fsutil_HandleLock(handlePtr);
  565.     handlePtr->rmt.recovery.use.ref--;
  566.     if (flags & FS_WRITE) {
  567.     handlePtr->rmt.recovery.use.write--;
  568.     }
  569.     if (flags & FS_EXECUTE) {
  570.     handlePtr->rmt.recovery.use.exec--;
  571.     }
  572.     Fsutil_HandleRelease(handlePtr, TRUE);
  573.     return(SUCCESS);
  574. }
  575.  
  576. /*
  577.  * ----------------------------------------------------------------------------
  578.  *
  579.  * FsrmtFileMigOpen --
  580.  *
  581.  *    Complete the creation of a FSIO_RMT_FILE_STREAM after migration.
  582.  *    
  583.  * Results:
  584.  *    SUCCESS (until FsRmtFileHandleInit returns differently)
  585.  *
  586.  * Side effects:
  587.  *    If SUCCESS, adds a reference and useCounts to the I/O handle.
  588.  *
  589.  * ----------------------------------------------------------------------------
  590.  *
  591.  */
  592. /*ARGSUSED*/
  593. ReturnStatus
  594. FsrmtFileMigOpen(migInfoPtr, size, data, hdrPtrPtr)
  595.     Fsio_MigInfo    *migInfoPtr;    /* Migration state */
  596.     int        size;        /* sizeof(Fsio_FileState), IGNORED */
  597.     ClientData    data;        /* Ref. to Fsio_FileState. */
  598.     Fs_HandleHeader **hdrPtrPtr;    /* Return - I/O handle for the file */
  599. {
  600.     ReturnStatus status;
  601.     register Fs_FileID *fileIDPtr = &migInfoPtr->ioFileID;
  602.     Fsrmt_FileIOHandle *handlePtr;
  603.  
  604.     status = FsrmtFileIoOpen(fileIDPtr, &migInfoPtr->flags, rpc_SpriteID,
  605.         data, (char *)NIL, (Fs_HandleHeader **)&handlePtr);
  606.     *hdrPtrPtr = (Fs_HandleHeader *)handlePtr;
  607.     return(status);
  608. }
  609.  
  610. /*
  611.  * ----------------------------------------------------------------------------
  612.  *
  613.  * FsrmtFileMigrate --
  614.  *
  615.  *    This causes a call to Fsio_FileMigrate on the server to shift
  616.  *    client references.  We may be the server after migration, in which
  617.  *    case the routine is called directly.  Otherwise an RPC is done
  618.  *    to the server. A useful side-effect of this routine is
  619.  *    to properly set the type in the ioFileID, either FSIO_LCL_FILE_STREAM
  620.  *    or FSIO_RMT_FILE_STREAM.
  621.  *
  622.  * Results:
  623.  *    The return code from Fsio_FileMigrate, or the RPC.
  624.  *    Returns Fsio_FileState for use by the MigEnd routine.
  625.  *
  626.  * Side effects:
  627.  *    Sets the correct stream type on the ioFileID.
  628.  *
  629.  * ----------------------------------------------------------------------------
  630.  *
  631.  */
  632. /*ARGSUSED*/
  633. ReturnStatus
  634. FsrmtFileMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr, sizePtr, dataPtr)
  635.     Fsio_MigInfo    *migInfoPtr;    /* Migration state */
  636.     int        dstClientID;    /* ID of target client */
  637.     int        *flagsPtr;    /* In/Out Stream usage flags */
  638.     int        *offsetPtr;    /* Return - the correct stream offset */
  639.     int        *sizePtr;    /* Return - sizeof(Fsio_FileState) */
  640.     Address    *dataPtr;    /* Return - pointer to Fsio_FileState */
  641. {
  642.     register ReturnStatus        status;
  643.     register Fsio_FileState        *fileStatePtr;
  644.  
  645.     if (migInfoPtr->ioFileID.serverID == rpc_SpriteID) {
  646.     /*
  647.      * The file was remote, which is why we were called, but is now local.
  648.      */
  649.     migInfoPtr->ioFileID.type = FSIO_LCL_FILE_STREAM;
  650.     return(Fsio_FileMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr,
  651.                 sizePtr, dataPtr));
  652.     }
  653.     migInfoPtr->ioFileID.type = FSIO_RMT_FILE_STREAM;
  654.     fileStatePtr = mnew(Fsio_FileState);
  655.     status = Fsrmt_NotifyOfMigration(migInfoPtr, flagsPtr, offsetPtr,
  656.         sizeof(Fsio_FileState), (Address)fileStatePtr);
  657.     if (status != SUCCESS) {
  658.     printf( "FsrmtFileMigrate, server error <%x>\n",
  659.         status);
  660.     } else {
  661.     *dataPtr = (Address)fileStatePtr;
  662.     *sizePtr = sizeof(Fsio_FileState);
  663.     }
  664.     return(status);
  665. }
  666.  
  667.  
  668. /*
  669.  *----------------------------------------------------------------------
  670.  *
  671.  * FsrmtFileRead --
  672.  *
  673.  *    Read from a remote file.  This tries the cache first, and then
  674.  *    goes remote if the file is not cacheable.  This also checks against
  675.  *    remotely shared streams (due to migration), and bypasses the cache
  676.  *    in that case.
  677.  *
  678.  * Results:
  679.  *    The results of Fscache_Read, or of the RPC.
  680.  *
  681.  * Side effects:
  682.  *    The *offsetPtr is updated to reflect the read.
  683.  *
  684.  *----------------------------------------------------------------------
  685.  */
  686. ReturnStatus
  687. FsrmtFileRead(streamPtr, readPtr, remoteWaitPtr, replyPtr)
  688.     Fs_Stream        *streamPtr;    /* Stream to a remote file. */
  689.     Fs_IOParam        *readPtr;    /* Read parameter block. */
  690.     Sync_RemoteWaiter    *remoteWaitPtr;    /* Process info for remote waiting */
  691.     Fs_IOReply        *replyPtr;    /* Signal to return, if any,
  692.                      * plus the amount read. */
  693. {
  694.     register Fsrmt_FileIOHandle *handlePtr =
  695.         (Fsrmt_FileIOHandle *)streamPtr->ioHandlePtr;
  696.     register ReturnStatus status;
  697.  
  698.     if (readPtr->flags & FS_RMT_SHARED) {
  699.     /*
  700.      * The stream is shared accross the network.  We have to go through
  701.      * to the file server to get the correct stream offset.
  702.      */
  703.     status = FS_NOT_CACHEABLE;
  704.     } else {
  705.     status = Fscache_Read(&handlePtr->cacheInfo, readPtr->flags,
  706.             readPtr->buffer, readPtr->offset, &readPtr->length,
  707.             remoteWaitPtr);
  708.     replyPtr->length = readPtr->length;
  709.     }
  710.     /*
  711.      * If not-cacheable then go to the remote file server.  Otherwise
  712.      * update the amount read in the reply because Fscache_Read uses
  713.      * the old-style in/out length variable.
  714.      */
  715.     if (status != FS_NOT_CACHEABLE) {
  716.     replyPtr->length = readPtr->length;
  717.     } else {
  718.     status = Fsrmt_Read(streamPtr, readPtr, remoteWaitPtr, replyPtr);
  719.     if (status == SUCCESS) {
  720.         if (readPtr->flags & FS_RMT_SHARED) {
  721.         fs_Stats.rmtIO.sharedStreamBytesRead += replyPtr->length;
  722.         } else {
  723.         fs_Stats.rmtIO.uncacheableBytesRead += replyPtr->length;
  724.         if (handlePtr->cacheInfo.flags & FSCACHE_IS_DIR) {
  725.             fs_Stats.rmtIO.uncacheableDirBytesRead += replyPtr->length;
  726.         }
  727.         }
  728.     }
  729.     }
  730.     return(status);
  731. }
  732.  
  733. /*
  734.  *----------------------------------------------------------------------
  735.  *
  736.  * FsrmtFileWrite --
  737.  *
  738.  *    Write to a remote file.  This checks for cachability and uses
  739.  *    either the cache write routine or an RPC stub.
  740.  *
  741.  * Results:
  742.  *    The results of Fscache_Write or the RPC.
  743.  *
  744.  * Side effects:
  745.  *    A buffer may have to allocated when doing an uncached write.
  746.  *
  747.  *----------------------------------------------------------------------
  748.  */
  749. ReturnStatus
  750. FsrmtFileWrite(streamPtr, writePtr, remoteWaitPtr, replyPtr)
  751.     Fs_Stream        *streamPtr;    /* Open stream to remote file. */
  752.     Fs_IOParam        *writePtr;    /* Read parameter block */
  753.     Sync_RemoteWaiter    *remoteWaitPtr;    /* Process info for remote waiting */
  754.     Fs_IOReply        *replyPtr;    /* Signal to return, if any */
  755. {
  756.     register Fsrmt_FileIOHandle *handlePtr =
  757.         (Fsrmt_FileIOHandle *)streamPtr->ioHandlePtr;
  758.     register ReturnStatus status;
  759.  
  760.     if (writePtr->flags & FS_RMT_SHARED) {
  761.     status = FS_NOT_CACHEABLE;
  762.     } else {
  763.     Fscache_WaitForReadAhead(&handlePtr->readAhead);
  764.     status = Fscache_Write(&handlePtr->cacheInfo, writePtr->flags,
  765.                   writePtr->buffer, writePtr->offset,
  766.                       &writePtr->length, remoteWaitPtr);
  767.     writePtr->flags &= ~FS_SERVER_WRITE_THRU;
  768.     Fscache_AllowReadAhead(&handlePtr->readAhead);
  769.     }
  770.     if (status != FS_NOT_CACHEABLE) {
  771.     replyPtr->length = writePtr->length;
  772.     } else {
  773.     status = Fsrmt_Write(streamPtr, writePtr, remoteWaitPtr, replyPtr);
  774.     if (status == SUCCESS) {
  775.         if (writePtr->flags & FS_RMT_SHARED) {
  776.         fs_Stats.rmtIO.sharedStreamBytesWritten += replyPtr->length;
  777.         } else {
  778.         fs_Stats.rmtIO.uncacheableBytesWritten += replyPtr->length;
  779.         }
  780.     }
  781.     }
  782.     return(status);
  783. }
  784.  
  785. /*
  786.  *----------------------------------------------------------------------
  787.  *
  788.  * FsrmtFilePageRead --
  789.  *
  790.  *    Do a page-in for a remote file.
  791.  *
  792.  * Results:
  793.  *    The results of Fscache_Read, or of Fsrmt_Read.
  794.  *
  795.  * Side effects:
  796.  *    None.
  797.  *
  798.  *----------------------------------------------------------------------
  799.  */
  800. ReturnStatus
  801. FsrmtFilePageRead(streamPtr, readPtr, remoteWaitPtr, replyPtr)
  802.     Fs_Stream        *streamPtr;    /* Stream to a remote file. */
  803.     Fs_IOParam        *readPtr;    /* Read parameter block. */
  804.     Sync_RemoteWaiter    *remoteWaitPtr;    /* Process info for remote waiting */
  805.     Fs_IOReply        *replyPtr;    /* Signal to return, if any,
  806.                      * plus the amount read. */
  807. {
  808.     register Fsrmt_FileIOHandle *handlePtr =
  809.         (Fsrmt_FileIOHandle *)streamPtr->ioHandlePtr;
  810.     register ReturnStatus status = SUCCESS;
  811.     int savedOffset = readPtr->offset;
  812.     int savedLength = readPtr->length;
  813.     Address savedBuffer = readPtr->buffer;
  814.     int blockNum, firstBlock, lastBlock, size, toRead;
  815.     Fscache_Block *blockPtr;
  816.     Boolean found;
  817.  
  818.     /*
  819.      * This should check if the file is cached if:
  820.      * a) it is not a FS_SWAP file or
  821.      * b) it is a shared file (which will be FS_SWAP)
  822.      * but for now we'll just always check.  - Ken
  823.      *
  824.      * This used to be
  825.      *        if ((readPtr->flags & FS_SWAP) == 0) {
  826.      * The problem is that shared files are marked swap, and we don't want
  827.      * to look in the cache for regular swap files, but we must for shared
  828.      * files.  We need another flag and there isn't one.  If we know it's
  829.      * a swap page, we should just do an Fsrmt_Read.
  830.      */
  831.  
  832.     /*
  833.      * This may be a CODE or HEAP page, so we check in our cache
  834.      * to see if we have it there;  we may have just written it.
  835.      * We are now, once again, attempting to special-case HEAP pages.
  836.      * We want to keep the clean copies in the cache so they can
  837.      * be re-read.
  838.      */
  839.     size = readPtr->length;
  840.     firstBlock = (unsigned int) readPtr->offset / FS_BLOCK_SIZE;
  841.     lastBlock = (unsigned int) (readPtr->offset + size - 1) /
  842.         FS_BLOCK_SIZE;
  843.     for (blockNum = firstBlock;
  844.      blockNum <= lastBlock; blockNum++) {
  845.     toRead = size;
  846.     if ((unsigned int) (readPtr->offset + size - 1)
  847.         / FS_BLOCK_SIZE > blockNum) {
  848.         toRead = (blockNum + 1) * FS_BLOCK_SIZE - readPtr->offset;
  849.     }
  850.     Fscache_FetchBlock(&handlePtr->cacheInfo, blockNum,
  851.         FSCACHE_DATA_BLOCK, &blockPtr, &found);
  852.     fs_Stats.blockCache.readAccesses++;
  853.     if (found) {
  854.             if (blockPtr->timeDirtied != 0) {
  855.                 fs_Stats.blockCache.readHitsOnDirtyBlock++;
  856.             } else {
  857.                 fs_Stats.blockCache.readHitsOnCleanBlock++;
  858.             }
  859.             if (blockPtr->flags & FSCACHE_READ_AHEAD_BLOCK) {
  860.                 fs_Stats.blockCache.readAheadHits++;
  861.             }
  862.         /*
  863.          * Update bytesRead after the successful FetchBlock.  The
  864.          * bytesRead counter counts all bytes read from the cache,
  865.          * including misses.
  866.          */
  867.         Fs_StatAdd(toRead, fs_Stats.blockCache.bytesRead,
  868.             fs_Stats.blockCache.bytesReadOverflow);
  869.         fs_Stats.rmtIO.hitsOnVMBlock++;
  870.         bcopy(blockPtr->blockAddr + (readPtr->offset &
  871.             FS_BLOCK_OFFSET_MASK), readPtr->buffer, toRead);
  872.         if (blockPtr->flags & FSCACHE_READ_AHEAD_BLOCK) {
  873.         fs_Stats.blockCache.readAheadHits++;
  874.         }
  875.         /*
  876.          * Let heap pages sit in the cache.
  877.          */
  878.         if (readPtr->flags & FS_HEAP) {
  879.         fs_Stats.rmtIO.hitsOnHeapBlock++;
  880.         Fscache_UnlockBlock(blockPtr, 0, -1, 0,
  881.             FSCACHE_CLEAR_READ_AHEAD);
  882.         } else {
  883.         if (readPtr->flags & FS_SWAP) {
  884.             fs_Stats.rmtIO.hitsOnSwapPage++;
  885.         } else if ((readPtr->flags & (FS_HEAP | FS_SWAP)) == 0) {
  886.             /* It's a code page */
  887.             fs_Stats.rmtIO.hitsOnCodePage++;
  888.         }
  889.         Fscache_UnlockBlock(blockPtr, 0, -1, 0,
  890.             FSCACHE_CLEAR_READ_AHEAD | FSCACHE_BLOCK_UNNEEDED);
  891.         }
  892.     } else {    /* Not found. */
  893.         fs_Stats.rmtIO.missesOnVMBlock++;
  894.         /*
  895.          * It's an initialized heap page.  Read it into the
  896.          * cache.
  897.          */
  898.         if ((readPtr->flags & FS_HEAP) &&
  899.             blockPtr != (Fscache_Block *) NIL) {
  900.         Fscache_FileInfo    *cacheInfoPtr;
  901.  
  902.         fs_Stats.rmtIO.missesOnHeapBlock++;
  903.         cacheInfoPtr = &handlePtr->cacheInfo;
  904.         status = (cacheInfoPtr->backendPtr->ioProcs.blockRead)
  905.             (cacheInfoPtr->hdrPtr, blockPtr, remoteWaitPtr);
  906.         if (status == SUCCESS) {
  907.             /* Copy to vm block */
  908.             bcopy(blockPtr->blockAddr + (readPtr->offset &
  909.                 FS_BLOCK_OFFSET_MASK), readPtr->buffer, toRead);
  910.             /*
  911.              * Update bytesRead after the read into a cache block.  The
  912.              * bytesRead counter counts all bytes read from the cache,
  913.              * including misses.  We don't update bytesRead for the
  914.              * non-heap block reads, since those won't be read into
  915.              * the cache.
  916.              */
  917.             Fs_StatAdd(toRead, fs_Stats.blockCache.bytesRead,
  918.                 fs_Stats.blockCache.bytesReadOverflow);
  919.             fs_Stats.rmtIO.bytesReadForVM += toRead;
  920.             fs_Stats.rmtIO.bytesReadForHeap += toRead;
  921.             Fscache_UnlockBlock(blockPtr, 0, -1, 0,
  922.                 FSCACHE_CLEAR_READ_AHEAD);
  923.         } else {
  924.             fs_Stats.blockCache.domainReadFails++;
  925.         }
  926.         }
  927.         if (status != SUCCESS || !(readPtr->flags & FS_HEAP) ||
  928.             blockPtr == (Fscache_Block *) NIL) {
  929.         if (blockPtr != (Fscache_Block *)NIL) {
  930.             Fscache_UnlockBlock(blockPtr, 0, -1, 0,
  931.             FSCACHE_DELETE_BLOCK);
  932.         }
  933.         if (readPtr->flags & FS_SWAP) {
  934.             fs_Stats.rmtIO.missesOnSwapPage++;
  935.         } else if ((readPtr->flags & (FS_HEAP | FS_SWAP)) == 0) {
  936.             /* It's a code page. */
  937.             fs_Stats.rmtIO.missesOnCodePage++;
  938.         }
  939.  
  940.         readPtr->length = toRead;
  941.         status = Fsrmt_Read(streamPtr, readPtr, remoteWaitPtr,
  942.             replyPtr);
  943.         if (status != SUCCESS) {
  944.             break;
  945.         }
  946.         fs_Stats.rmtIO.bytesReadForVM += toRead;
  947.         if (readPtr->flags & FS_HEAP) {
  948.             fs_Stats.rmtIO.bytesReadForHeapUncached += toRead;
  949.         }
  950.         }
  951.     }
  952.     /*
  953.      * Successfully read one FS block, either remotely or from
  954.      * the cache.  Update pointers and loop.
  955.      */
  956.     size -= toRead;
  957.     readPtr->offset += toRead;
  958.     readPtr->buffer += toRead;
  959.     }
  960.     if (status != SUCCESS) {
  961.     readPtr->offset = savedOffset;
  962.     readPtr->length = savedLength;
  963.     readPtr->buffer = savedBuffer;
  964.     }
  965.     return(status);
  966. }
  967.  
  968. /*
  969.  *----------------------------------------------------------------------
  970.  *
  971.  * FsrmtFilePageWrite --
  972.  *
  973.  *    Do a page-out for a remote file.
  974.  *    NB: this knows that remote block allocation is a no-op, so
  975.  *    there is no call to the allocation routine.
  976.  *
  977.  * Results:
  978.  *    The results of Fsrmt_Write.
  979.  *
  980.  * Side effects:
  981.  *    Statistics are taken.  (This could be replaced with Fsrmt_Write
  982.  *    if these statistics aren't needed.)
  983.  *
  984.  *----------------------------------------------------------------------
  985.  */
  986. ReturnStatus
  987. FsrmtFilePageWrite(streamPtr, writePtr, remoteWaitPtr, replyPtr)
  988.     Fs_Stream        *streamPtr;    /* Open stream to remote file. */
  989.     Fs_IOParam        *writePtr;    /* Read parameter block */
  990.     Sync_RemoteWaiter    *remoteWaitPtr;    /* Process info for remote waiting */
  991.     Fs_IOReply        *replyPtr;    /* Signal to return, if any */
  992. {
  993.     ReturnStatus status;
  994.  
  995.     status = Fsrmt_Write(streamPtr, writePtr, remoteWaitPtr, replyPtr);
  996.     if (status == SUCCESS) {
  997.     fs_Stats.rmtIO.bytesWrittenForVM += replyPtr->length;
  998.     }
  999.     return(status);
  1000. }
  1001.  
  1002. /*
  1003.  *----------------------------------------------------------------------
  1004.  *
  1005.  * FsrmtFileBlockRead --
  1006.  *
  1007.  *    Read in a cache block for a remote file.
  1008.  *
  1009.  * Results:
  1010.  *    The return code from the server.
  1011.  *
  1012.  * Side effects:
  1013.  *    This sets the blockPtr->blockSize to be the actual amount of
  1014.  *    data read into the block.  Any left over space is zero filled.
  1015.  *
  1016.  *----------------------------------------------------------------------
  1017.  */
  1018. static ReturnStatus
  1019. FsrmtFileBlockRead(hdrPtr, blockPtr, waitPtr)
  1020.     Fs_HandleHeader *hdrPtr;    /* Pointer to handle for file to write to. */
  1021.     Fscache_Block *blockPtr;    /* Block to read in.  blockNum is the logical
  1022.                  * block and indicates the offset.  blockSize
  1023.                  * is set to FS_BLOCK_SIZE, but we reduce
  1024.                  * that if less gets read.  blockAddr is
  1025.                  * the memory area for the block. */
  1026.     Sync_RemoteWaiter *waitPtr;    /* For remote waiting if remote cache is full */
  1027. {
  1028.     Fs_Stream        dummyStream;
  1029.     Fs_IOParam        io;
  1030.     Fs_IOReply        reply;
  1031.     ReturnStatus    status;
  1032.  
  1033.     dummyStream.hdr.fileID.type = -1;
  1034.     dummyStream.ioHandlePtr = hdrPtr;
  1035.  
  1036.     io.buffer = blockPtr->blockAddr;
  1037.     io.length = FS_BLOCK_SIZE;
  1038.     io.offset = blockPtr->blockNum * FS_BLOCK_SIZE;
  1039.     io.flags = 0;
  1040.  
  1041.     status = Fsrmt_Read(&dummyStream, &io, waitPtr, &reply);
  1042.     blockPtr->blockSize = reply.length;
  1043.     if (blockPtr->blockSize < FS_BLOCK_SIZE) {
  1044.     /*
  1045.      * We always must make sure that every cache block is filled
  1046.      * with zeroes.  Since we didn't read a full block zero fill
  1047.      * the rest.
  1048.      */
  1049.     fs_Stats.blockCache.readZeroFills++;
  1050.     bzero(blockPtr->blockAddr + blockPtr->blockSize,
  1051.         FS_BLOCK_SIZE - blockPtr->blockSize);
  1052.     }
  1053.     fs_Stats.rmtIO.bytesReadForCache += blockPtr->blockSize;
  1054.     return(status);
  1055. }
  1056.  
  1057. /*
  1058.  *----------------------------------------------------------------------
  1059.  *
  1060.  * FsrmtFileBlockWrite --
  1061.  *
  1062.  *    Write out a cache block for a remote file.  This understands
  1063.  *    that the diskBlock is the same as the (logical) blockNum
  1064.  *    of the block.  It marks the write as coming from a client cache
  1065.  *    so the server doesn't update the modify time of the file.
  1066.  *
  1067.  *
  1068.  * Results:
  1069.  *    The return code from the RPC.
  1070.  *
  1071.  * Side effects:
  1072.  *    The write.
  1073.  *
  1074.  *----------------------------------------------------------------------
  1075.  */
  1076. static ReturnStatus
  1077. FsrmtFileBlockWrite(hdrPtr, blockPtr, flags)
  1078.     Fs_HandleHeader *hdrPtr;    /* I/O handle of file to write. */
  1079.     Fscache_Block *blockPtr;    /* The cache block to write. */
  1080.     int        flags;
  1081. {
  1082.     ReturnStatus    status;
  1083.     Fs_Stream        dummyStream;
  1084.     Fs_IOParam        io;
  1085.     Fs_IOReply        reply;
  1086.  
  1087.     /*
  1088.      *    The server recognizes the write RPC as coming from the
  1089.      *    cache (FS_CLIENT_CACHE_WRITE) and ignores the streamID.
  1090.      */
  1091.     dummyStream.hdr.fileID.type = -1;
  1092.     dummyStream.ioHandlePtr = hdrPtr;
  1093.  
  1094.     io.buffer = blockPtr->blockAddr;
  1095.     io.length = blockPtr->blockSize;
  1096.     io.offset = blockPtr->diskBlock * FS_BLOCK_SIZE; /* diskBlock == blockNum */
  1097.     io.flags = flags | FS_CLIENT_CACHE_WRITE;
  1098.  
  1099.     status = Fsrmt_Write(&dummyStream, &io, (Sync_RemoteWaiter *)NIL, &reply);
  1100.     if (status == SUCCESS) {
  1101.     fs_Stats.rmtIO.bytesWrittenFromCache += blockPtr->blockSize;
  1102.     }
  1103.     return(status);
  1104. }
  1105.  
  1106. /*
  1107.  *----------------------------------------------------------------------
  1108.  *
  1109.  * FsrmtFileBlockAllocate --
  1110.  *
  1111.  *    Allocate disk space for a remote file.  This always works, ie.
  1112.  *    the server is not contacted.  The offset is just mapped to a
  1113.  *    logical block number for the file.
  1114.  *
  1115.  *    IF THIS IS CHANGED TO ACTUALLY DO SOMETHING, then please add
  1116.  *    a call to this routine in FsrmtFilePageWrite.
  1117.  *
  1118.  * Results:
  1119.  *    None.
  1120.  *
  1121.  * Side effects:
  1122.  *    None.
  1123.  *
  1124.  *----------------------------------------------------------------------
  1125.  */
  1126. /*ARGSUSED*/
  1127. static ReturnStatus
  1128. FsrmtFileBlockAllocate(hdrPtr, offset, numBytes, flags, blockAddrPtr, newBlockPtr)
  1129.     Fs_HandleHeader    *hdrPtr;    /* Local file handle. */
  1130.     int         offset;        /* Offset to allocate at. */
  1131.     int         numBytes;    /* Number of bytes to allocate. */
  1132.     int            flags;        /* FSCACHE_DONT_BLOCK */
  1133.     int            *blockAddrPtr;     /* Disk address of block allocated. */
  1134.     Boolean        *newBlockPtr;    /* TRUE if there was no block allocated
  1135.                      * before. */
  1136. {
  1137.     *newBlockPtr = FALSE;
  1138.     *blockAddrPtr = offset / FS_BLOCK_SIZE;
  1139.     return(SUCCESS);
  1140. }
  1141.  
  1142. /*
  1143.  *----------------------------------------------------------------------
  1144.  *
  1145.  * FsrmtFileTrunc --
  1146.  *
  1147.  *    Truncate a remote file. Nothing need be done is the remote case
  1148.  *    since all the work is done on the file server.
  1149.  *
  1150.  * Results:
  1151.  *    SUCCESS
  1152.  *
  1153.  * Side effects:
  1154.  *
  1155.  *----------------------------------------------------------------------
  1156.  */
  1157. /*ARGSUSED*/
  1158. static ReturnStatus
  1159. FsrmtFileTrunc(hdrPtr, size, delete)
  1160.     Fs_HandleHeader *hdrPtr;    /* I/O handle for the file. */
  1161.     int            size;    /* Size to truncate to. */
  1162.     Boolean        delete;    /* True if the file is being deleted. */
  1163. {
  1164.     return SUCCESS;
  1165. }
  1166.  
  1167. /*
  1168.  *----------------------------------------------------------------------
  1169.  *
  1170.  * FsrmtFileIOControl --
  1171.  *
  1172.  *    IOControls for remote regular files.  Note, no byte order
  1173.  *    checking/fixing is down here as this is always called directly from
  1174.  *    a process, never via RPC.
  1175.  *
  1176.  * Results:
  1177.  *    An error code from the command.
  1178.  *
  1179.  * Side effects:
  1180.  *    Command dependent.
  1181.  *
  1182.  *----------------------------------------------------------------------
  1183.  */
  1184.  
  1185. /*ARGSUSED*/
  1186. ReturnStatus
  1187. FsrmtFileIOControl(streamPtr, ioctlPtr, replyPtr)
  1188.     Fs_Stream *streamPtr;        /* Stream to remote file */
  1189.     Fs_IOCParam *ioctlPtr;        /* I/O Control parameter block */
  1190.     Fs_IOReply *replyPtr;        /* Return length and signal */
  1191. {
  1192.     register Fsrmt_FileIOHandle *handlePtr =
  1193.         (Fsrmt_FileIOHandle *)streamPtr->ioHandlePtr;
  1194.     register ReturnStatus status;
  1195.  
  1196.     Fsutil_HandleLock(handlePtr);
  1197.     switch(ioctlPtr->command) {
  1198.     case IOC_REPOSITION: {
  1199.         if (streamPtr->flags & FS_RMT_SHARED) {
  1200.         status = Fsrmt_IOControl(streamPtr, ioctlPtr, replyPtr);
  1201.         } else {
  1202.         status = SUCCESS;
  1203.         }
  1204.         break;
  1205.     }
  1206.     case IOC_GET_FLAGS:
  1207.         if (ioctlPtr->outBufSize >= sizeof(int)) {
  1208.         *(int *)ioctlPtr->outBuffer = 0;
  1209.         }
  1210.         status = SUCCESS;
  1211.         break;
  1212.     case IOC_SET_FLAGS:
  1213.     case IOC_SET_BITS:
  1214.     case IOC_CLEAR_BITS:
  1215.         status = SUCCESS;
  1216.         break;
  1217.     case IOC_TRUNCATE:
  1218.         if ((streamPtr->flags & FS_WRITE) == 0) {
  1219.         status = FS_NO_ACCESS;
  1220.         } else if (ioctlPtr->inBufSize >= sizeof(int)) {
  1221.         register int length = *(int *)ioctlPtr->inBuffer;
  1222.         Fscache_Trunc(&handlePtr->cacheInfo, length, 0);
  1223.         status = Fsrmt_IOControl(streamPtr, ioctlPtr, replyPtr);
  1224.         } else {
  1225.         status = GEN_INVALID_ARG;
  1226.         }
  1227.         break;
  1228.     case IOC_MAP:
  1229.         if (ioctlPtr->inBufSize >= sizeof(int)) {
  1230.         status = Fsrmt_IOControl(streamPtr, ioctlPtr, replyPtr);
  1231.         } else {
  1232.         status = GEN_INVALID_ARG;
  1233.         }
  1234.         break;
  1235.     case IOC_LOCK:
  1236.     case IOC_UNLOCK:
  1237.         status = Fsrmt_IOControl(streamPtr, ioctlPtr, replyPtr);
  1238.         break;
  1239.     case IOC_NUM_READABLE: {
  1240.         register int bytesAvailable;
  1241.         register int streamOffset;
  1242.  
  1243.         if (ioctlPtr->outBufSize < sizeof(int)) {
  1244.         return(GEN_INVALID_ARG);
  1245.         }
  1246.         streamOffset = *(int *)ioctlPtr->inBuffer;
  1247.         bytesAvailable = handlePtr->cacheInfo.attr.lastByte + 1 -
  1248.                 streamOffset;
  1249.         *(int *)ioctlPtr->outBuffer = bytesAvailable;
  1250.         status = SUCCESS;
  1251.         break;
  1252.     }
  1253.     case IOC_SET_OWNER:
  1254.     case IOC_GET_OWNER:
  1255.         status = GEN_NOT_IMPLEMENTED;
  1256.         break;
  1257.     case IOC_PREFIX:
  1258.         status = SUCCESS;
  1259.         break;
  1260.     case IOC_WRITE_BACK: {
  1261.         /*
  1262.          * Write out the cached data for the file.
  1263.          */
  1264.         Ioc_WriteBackArgs *argPtr = (Ioc_WriteBackArgs *)ioctlPtr->inBuffer;
  1265.         Fscache_FileInfo *cacheInfoPtr = &handlePtr->cacheInfo;
  1266.  
  1267.         if (ioctlPtr->inBufSize < sizeof(Ioc_WriteBackArgs)) {
  1268.         status = GEN_INVALID_ARG;
  1269.         } else {
  1270.         int firstBlock, lastBlock;
  1271.         int blocksSkipped;
  1272.         int flags = 0;
  1273.         if (argPtr->shouldBlock) {
  1274.             flags |= FSCACHE_FILE_WB_WAIT;
  1275.         }
  1276.         if (argPtr->firstByte > 0) {
  1277.             firstBlock = argPtr->firstByte / FS_BLOCK_SIZE;
  1278.         } else {
  1279.             firstBlock = 0;
  1280.         }
  1281.         if (argPtr->lastByte > 0) {
  1282.             lastBlock = argPtr->lastByte / FS_BLOCK_SIZE;
  1283.         } else {
  1284.             lastBlock = FSCACHE_LAST_BLOCK;
  1285.         }
  1286.         status = Fscache_FileWriteBack(cacheInfoPtr, firstBlock,
  1287.             lastBlock, flags, &blocksSkipped);
  1288.         if (status == SUCCESS) {
  1289.             /*
  1290.              * Perform the IOC_WRITE_BACK on the file server to 
  1291.              * insure that the file is forced to disk.
  1292.              */
  1293.             status = Fsrmt_IOControl(streamPtr, ioctlPtr, replyPtr);
  1294. #define FILE_SERVER_IOC_WRITE_BACK_BROKEN
  1295. #ifdef FILE_SERVER_IOC_WRITE_BACK_BROKEN
  1296.             if (status == GEN_INVALID_ARG) {
  1297.             /*
  1298.              * Currently, IOC_WRITE_BACK don't work to machines
  1299.              * with different byte orders. This has been fixed
  1300.              * but until all file servers run the kernel we
  1301.              * patch round the bug. 
  1302.              * THIS CODE CAN BE REMOVED when all file servers
  1303.              * are running a version > 1.075.
  1304.              */
  1305.             status = SUCCESS;
  1306.             }
  1307. #endif /* FILE_SERVER_IOC_WRITE_BACK_BROKEN */
  1308.         }
  1309.  
  1310.         }
  1311.         break;
  1312.     }
  1313.     default:
  1314.         status = GEN_INVALID_ARG;
  1315.         break;
  1316.     }
  1317.     Fsutil_HandleUnlock(handlePtr);
  1318.     return(status);
  1319. }
  1320.  
  1321. /*
  1322.  *----------------------------------------------------------------------
  1323.  *
  1324.  * FsrmtFileGetIOAttr --
  1325.  *
  1326.  *    Update the attributes of a remotely served file from attributes
  1327.  *    that we have cached here.  The file server will have contacted
  1328.  *    other clients that may be caching the file, but we still need
  1329.  *    to check our own version of the access/modify times that we
  1330.  *    (might) have cached.
  1331.  *
  1332.  * Results:
  1333.  *    SUCCESS        - always returned.
  1334.  *
  1335.  * Side effects:
  1336.  *    Fills in the access time, modify time, and size from information
  1337.  *    we have cached here.
  1338.  *
  1339.  *----------------------------------------------------------------------
  1340.  */
  1341. /*ARGSUSED*/
  1342. ReturnStatus
  1343. FsrmtFileGetIOAttr(fileIDPtr, clientID, attrPtr)
  1344.     Fs_FileID        *fileIDPtr;    /* ID on the file */
  1345.     int            clientID;    /* Host ID of calling process */
  1346.     Fs_Attributes    *attrPtr;    /* Attributes to update */
  1347. {
  1348.     Fsrmt_FileIOHandle *handlePtr;
  1349.  
  1350.     handlePtr = Fsutil_HandleFetchType(Fsrmt_FileIOHandle, fileIDPtr);
  1351.     if (handlePtr != (Fsrmt_FileIOHandle *)NIL) {
  1352.     Fscache_UpdateAttrFromCache(&handlePtr->cacheInfo, attrPtr);
  1353.     Fsutil_HandleRelease(handlePtr, TRUE);
  1354.     }
  1355.     return(SUCCESS);
  1356. }
  1357.  
  1358. /*
  1359.  *----------------------------------------------------------------------
  1360.  *
  1361.  * FsrmtFileSetIOAttr --
  1362.  *
  1363.  *    Set the attributes of a remotely served file.  This routine is
  1364.  *    called after the file server has been contacted, so its only
  1365.  *    job is to update attributes we have cached here on the client.
  1366.  *
  1367.  * Results:
  1368.  *    SUCCESS or FS_STALE_HANDLE.
  1369.  *
  1370.  * Side effects:
  1371.  *    Updates the access time, modify time, and size that
  1372.  *    we have cached here.
  1373.  *
  1374.  *----------------------------------------------------------------------
  1375.  */
  1376. /*ARGSUSED*/
  1377. ReturnStatus
  1378. FsrmtFileSetIOAttr(fileIDPtr, attrPtr, flags)
  1379.     Fs_FileID        *fileIDPtr;    /* ID on the file */
  1380.     Fs_Attributes    *attrPtr;    /* Attributes to update */
  1381.     int            flags;        /* What attrs to set */
  1382. {
  1383.     Fsrmt_FileIOHandle *handlePtr;
  1384.  
  1385.     handlePtr = Fsutil_HandleFetchType(Fsrmt_FileIOHandle, fileIDPtr);
  1386.     if (handlePtr != (Fsrmt_FileIOHandle *)NIL) {
  1387.     Fscache_UpdateCachedAttr(&handlePtr->cacheInfo, attrPtr, flags);
  1388.     Fsutil_HandleRelease(handlePtr, TRUE);
  1389.     }
  1390.     return(SUCCESS);
  1391. }
  1392.  
  1393. static void FsrmtCleanBlocks _ARGS_((ClientData    data,
  1394.                 Proc_CallInfo *callInfoPtr));
  1395.  
  1396.  
  1397. /*
  1398.  *----------------------------------------------------------------------
  1399.  *
  1400.  * FsrmtStartWriteBack --
  1401.  *
  1402.  *     Start a block cleaner process for the specified domain.
  1403.  *
  1404.  * Results:
  1405.  *    TRUE if a block cleaner was started.
  1406.  *
  1407.  * Side effects:
  1408.  *    Number of block cleaner processes may be incremented.
  1409.  *
  1410.  * ----------------------------------------------------------------------------
  1411.  */
  1412. static Boolean
  1413. FsrmtStartWriteBack(backendPtr, fileFsynced)
  1414.     Fscache_Backend *backendPtr;    /* Backend to start writeback. */
  1415.     Boolean fileFsynced;        /* For ASPLOS only. */
  1416. {
  1417.     LOCK_MONITOR;
  1418.  
  1419.     if (fsrmtBlockCleaners < fscache_MaxBlockCleaners) {
  1420.     Proc_CallFunc(FsrmtCleanBlocks, (ClientData) backendPtr, 0);
  1421.     fsrmtBlockCleaners++;
  1422.     UNLOCK_MONITOR;
  1423.     return TRUE;
  1424.     }
  1425.     UNLOCK_MONITOR;
  1426.     return FALSE;
  1427. }
  1428.  
  1429.  
  1430. /*
  1431.  * ----------------------------------------------------------------------------
  1432.  *
  1433.  *    Functions to clean dirty blocks.
  1434.  *
  1435.  * ----------------------------------------------------------------------------
  1436.  */
  1437.  
  1438.  
  1439. /*
  1440.  * ----------------------------------------------------------------------------
  1441.  *
  1442.  * FsrmtCleanBlocks
  1443.  *
  1444.  *    Write all blocks on the dirty list to disk.  Called either from
  1445.  *    a block cleaner process or synchronously during system shutdown.
  1446.  *
  1447.  * Results:
  1448.  *         None.
  1449.  *
  1450.  * Side effects:
  1451.  *         The dirty list is emptied.
  1452.  *
  1453.  * ----------------------------------------------------------------------------
  1454.  */
  1455. /*ARGSUSED*/
  1456. static void
  1457. FsrmtCleanBlocks(data, callInfoPtr)
  1458.     ClientData        data;        /* Background flag.  If TRUE it means
  1459.                      * we are called from a block cleaner
  1460.                      * process.  Otherwise we being called
  1461.                      * synchrounously during a shutdown */
  1462.     Proc_CallInfo    *callInfoPtr;    /* Not Used. */
  1463. {
  1464.     Fscache_Block    *blockPtr;
  1465.     ReturnStatus        status;
  1466.     int                lastDirtyBlock;
  1467.     Fscache_FileInfo        *cacheInfoPtr;
  1468.     Fscache_Backend        *backendPtr;
  1469.  
  1470.     backendPtr = (Fscache_Backend *) data;
  1471.     cacheInfoPtr = Fscache_GetDirtyFile(backendPtr, TRUE, 
  1472.         FileMatch, (ClientData) 0);
  1473.     while (cacheInfoPtr != (Fscache_FileInfo *)NIL) {
  1474.     blockPtr = Fscache_GetDirtyBlock(cacheInfoPtr, BlockMatch,
  1475.             (ClientData) 0,  &lastDirtyBlock);
  1476.     while (blockPtr != (Fscache_Block *) NIL) {
  1477.         /*
  1478.          * Write the block.
  1479.          */
  1480.         status = backendPtr->ioProcs.blockWrite
  1481.             (cacheInfoPtr->hdrPtr, blockPtr, 
  1482.             lastDirtyBlock ? FS_LAST_DIRTY_BLOCK : 0);
  1483.         Fscache_ReturnDirtyBlock( blockPtr, status);
  1484.         blockPtr = Fscache_GetDirtyBlock(cacheInfoPtr, BlockMatch,
  1485.             (ClientData) 0, &lastDirtyBlock);
  1486.     }
  1487.     Fscache_ReturnDirtyFile(cacheInfoPtr, FALSE);
  1488.     cacheInfoPtr = Fscache_GetDirtyFile(backendPtr, TRUE,
  1489.             FileMatch, (ClientData) 0);
  1490.     }
  1491.     FscacheBackendIdle(backendPtr);
  1492.     LOCK_MONITOR;
  1493.     fsrmtBlockCleaners--;
  1494.     UNLOCK_MONITOR;
  1495. }
  1496.  
  1497.  
  1498.  
  1499. /*
  1500.  * ----------------------------------------------------------------------------
  1501.  *
  1502.  * FsrmtReallocBlock --
  1503.  *
  1504.  *     Reallocate a block which got a write error.
  1505.  *
  1506.  * Results:
  1507.  *    None.
  1508.  *
  1509.  * Side effects:
  1510.  *
  1511.  * ----------------------------------------------------------------------------
  1512.  */
  1513. /*ARGSUSED*/
  1514. static void
  1515. FsrmtReallocBlock(data, callInfoPtr)
  1516.     ClientData        data;            /* Block to move */
  1517.     Proc_CallInfo    *callInfoPtr;        /* Not used. */
  1518. {
  1519.     panic("FsrmtReallocBlock called\n");
  1520. }
  1521.  
  1522. /*
  1523.  * ----------------------------------------------------------------------------
  1524.  *
  1525.  * BlockMatch --
  1526.  *
  1527.  *     Cache backend block type match.  Fsrmt doesn't care about the 
  1528.  *    order of blocks returned by GetDirtyBlocks.
  1529.  *
  1530.  * Results:
  1531.  *    TRUE.
  1532.  *
  1533.  * Side effects:
  1534.  *
  1535.  * ----------------------------------------------------------------------------
  1536.  */
  1537. /*ARGSUSED*/
  1538. static Boolean
  1539. BlockMatch( blockPtr, cleintData)
  1540.     Fscache_Block *blockPtr;
  1541.     ClientData    cleintData;
  1542. {
  1543.     return TRUE;
  1544. }
  1545.  
  1546. /*
  1547.  * ----------------------------------------------------------------------------
  1548.  *
  1549.  * FileMatch --
  1550.  *
  1551.  *     Cache backend files match.  Fsrmt doesn't care about the 
  1552.  *    order of files returned by GetDirtyFiles.
  1553.  *
  1554.  * Results:
  1555.  *    TRUE.
  1556.  *
  1557.  * Side effects:
  1558.  *
  1559.  * ----------------------------------------------------------------------------
  1560.  */
  1561. /*ARGSUSED*/
  1562. static Boolean
  1563. FileMatch( cacheInfoPtr, cleintData)
  1564.     Fscache_FileInfo *cacheInfoPtr;
  1565.     ClientData    cleintData;
  1566. {
  1567.     return TRUE;
  1568. }
  1569.  
  1570.  
  1571. /*
  1572.  *----------------------------------------------------------------------------
  1573.  *
  1574.  * FsrmtSetupFileReopen --
  1575.  *
  1576.  *    Set up the data for an RPC to reopen a file handle.
  1577.  *
  1578.  * Results:
  1579.  *    Return status.
  1580.  *
  1581.  * Side effects:
  1582.  *    Data structure set up.
  1583.  *
  1584.  *----------------------------------------------------------------------------
  1585.  */
  1586. ReturnStatus
  1587. FsrmtSetupFileReopen(hdrPtr, paramsPtr)
  1588.     Fs_HandleHeader        *hdrPtr;
  1589.     Address            paramsPtr;
  1590. {
  1591.     Fsrmt_FileIOHandle        *rmtHandlePtr;
  1592.     int                numDirtyBlocks;
  1593.     Fsio_FileReopenParams    *reopenParamsPtr =
  1594.                     (Fsio_FileReopenParams *) paramsPtr;
  1595.     Boolean            okayToScavenge;
  1596.  
  1597.     rmtHandlePtr = (Fsrmt_FileIOHandle *) hdrPtr;
  1598.     numDirtyBlocks = Fscache_PreventWriteBacks(&rmtHandlePtr->cacheInfo);
  1599.     Fscache_AllowWriteBacks(&rmtHandlePtr->cacheInfo);
  1600.     /*
  1601.      * Optimize out re-opens for files that aren't being waited
  1602.      * on, that have no users, and that have no blocks in the cache.
  1603.      * I don't call OkToScavenge from fsutilHandleScavenge.c, since I think
  1604.      * it's okay to do this even if there's already an active scavenger,
  1605.      * because it will have locked the handle if it's working on it.
  1606.      */
  1607.     okayToScavenge = Fscache_OkToScavengeExceptDirty(&rmtHandlePtr->cacheInfo);
  1608.  
  1609.     if (recov_SkipCleanFiles && (rmtHandlePtr->rmt.recovery.use.ref == 0 &&
  1610.         okayToScavenge &&
  1611.         !Fsutil_RecoveryNeeded(&rmtHandlePtr->rmt.recovery))) {
  1612.     fs_Stats.recovery.reopensAvoided++;
  1613.     return FS_RECOV_SKIP;
  1614.     } else if ((rmtHandlePtr->rmt.recovery.use.ref == 0 && okayToScavenge &&
  1615.         !Fsutil_RecoveryNeeded(&rmtHandlePtr->rmt.recovery))) {
  1616.         Vm_FileChanged(&rmtHandlePtr->segPtr);
  1617.         Fsutil_RecoverySyncLockCleanup(&rmtHandlePtr->rmt.recovery);
  1618.         Fscache_InfoSyncLockCleanup(&rmtHandlePtr->cacheInfo);
  1619.         Fscache_ReadAheadSyncLockCleanup(&rmtHandlePtr->readAhead);
  1620.         Fsutil_HandleRemove(rmtHandlePtr);
  1621.         fs_Stats.object.rmtFiles--;
  1622.     fs_Stats.recovery.reopensAvoided++;
  1623.     return FS_NO_HANDLE;
  1624.     }
  1625.     
  1626. /* for debugging */
  1627. #define    FS_HANDLE_INVALID 0x20
  1628.     if (hdrPtr->flags & FS_HANDLE_INVALID) {
  1629.     printf("Attempting to recover invalid file handle <%d,0x%x,0x%x>\n",
  1630.         hdrPtr->fileID.serverID, hdrPtr->fileID.major,
  1631.         hdrPtr->fileID.minor);
  1632.     return FAILURE;
  1633.     }
  1634. /* end for debugging */
  1635.  
  1636.     reopenParamsPtr->flags = rmtHandlePtr->flags;
  1637.     if (numDirtyBlocks > 0) {
  1638.     reopenParamsPtr->flags |= FSIO_HAVE_BLOCKS;
  1639.     }
  1640.     reopenParamsPtr->fileID = hdrPtr->fileID;
  1641.     reopenParamsPtr->fileID.type = FSIO_LCL_FILE_STREAM;
  1642.     reopenParamsPtr->prefixFileID.type = NIL;    /* not used */
  1643.     reopenParamsPtr->use = rmtHandlePtr->rmt.recovery.use;
  1644.     reopenParamsPtr->version = rmtHandlePtr->cacheInfo.version;
  1645.  
  1646.     return SUCCESS;
  1647. }
  1648.  
  1649.  
  1650. /*
  1651.  *----------------------------------------------------------------------------
  1652.  *
  1653.  * FsrmtFinishFileReopen --
  1654.  *
  1655.  *    Do post-processing for a file handle after bulk reopen.
  1656.  *
  1657.  * Results:
  1658.  *    None.
  1659.  *
  1660.  * Side effects:
  1661.  *    Write-backs, etc., may occur.
  1662.  *
  1663.  *----------------------------------------------------------------------------
  1664.  */
  1665. void
  1666. FsrmtFinishFileReopen(hdrPtr, statePtr, status)
  1667.     Fs_HandleHeader        *hdrPtr;
  1668.     Address            statePtr;
  1669.     ReturnStatus        status;
  1670. {
  1671.     Fsrmt_FileIOHandle        *rmtHandlePtr;
  1672.     int                numDirtyBlocks;
  1673.     Fsio_FileState        *fileStatePtr = (Fsio_FileState *) statePtr;
  1674.  
  1675.     rmtHandlePtr = (Fsrmt_FileIOHandle *) hdrPtr;
  1676.     numDirtyBlocks = Fscache_PreventWriteBacks(&rmtHandlePtr->cacheInfo);
  1677.     Fscache_AllowWriteBacks(&rmtHandlePtr->cacheInfo);
  1678.     if (status != SUCCESS) {
  1679.     if (numDirtyBlocks > 0) {
  1680.         printf(
  1681. "Re-open failed <%x> with dirty blocks in cache, \"%s\" <%d,%d> server %d\n",
  1682.         status, Fsutil_HandleName(hdrPtr), hdrPtr->fileID.major,
  1683.         hdrPtr->fileID.minor, hdrPtr->fileID.serverID);
  1684.     }
  1685.     if (status != RPC_TIMEOUT &&
  1686.         status != RPC_SERVICE_DISABLED) {
  1687.         /*
  1688.          * Nuke the cache because our caller will nuke the handle.
  1689.          */
  1690.         Fscache_FileInvalidate(&rmtHandlePtr->cacheInfo, 0, FSCACHE_LAST_BLOCK);
  1691.     }
  1692.     } else {
  1693.     /*
  1694.      * Flush any lanquishing dirty blocks back to the server.
  1695.      */
  1696.     if (numDirtyBlocks > 0) {
  1697.         int skipped;
  1698.         (void) Fscache_FileWriteBack(&rmtHandlePtr->cacheInfo, 0,
  1699.                 FSCACHE_LAST_BLOCK, 0, &skipped);
  1700.     }
  1701.     /*
  1702.      * Update the handle - take care of cache flushes, updating cached
  1703.      * attributes, etc.
  1704.      */
  1705.     if (Fscache_UpdateFile(&rmtHandlePtr->cacheInfo,
  1706.             rmtHandlePtr->rmt.recovery.use.write,
  1707.             fileStatePtr->version, fileStatePtr->cacheable,
  1708.             &fileStatePtr->attr)) {
  1709.         Vm_FileChanged(&rmtHandlePtr->segPtr);
  1710.     }
  1711.  
  1712.     rmtHandlePtr->openTimeStamp = fileStatePtr->openTimeStamp;
  1713.     }
  1714.     return;
  1715. }
  1716.